<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>

    <script>
        //JS 立即执行函数可以让函数在创建后立即执行 主要是用于隔离作用域。
        //立即执行函数通常有下面两种写法：
        //第一种写法
        (function () {

        })();
        //第二种写法
        (function () {

        }());
        // //立即执行函数只有一个作用：创建一个独立的作用域。这个作用域里面的变量，外面访问不到（即避免了「变量污染」）
        // var liList = document.getElementsByTagName('li');
        // for (var i = 0; i < 6; i++) {
        //     liList[i].onclick = function () {
        //         alert(i) // 为什么 alert 出来的总是 6，而不是 0、1、2、3、4、5
        //     }
        // }
        //因为输出的 i 是全局作用域的，当循环结束后 i 的值是 6，所以输出的 i 就是6。
        //用立即执行函数可以解决这个问题。
        var liList = document.getElementsByTagName('li')
        for (var i = 0; i < 6; i++) {
            (function (j) {
                liList[j].onclick = function () {
                    alert(j) // 0、1、2、3、4、5
                }
            })(i)
        }
        // 因为 JS 中调用函数传递参数都是值传递 ，所以当立即执行函数执行时，
        //首先会把参数 i 的值复制一份，然后再创建函数作用域来执行函数，循环5次就会创建5个作用域，所以每个 li 元素访问的都是不同作用域的 i 的值 。
        for (var i = 0; i < 5; i++) {
            (function (i) {
                setTimeout(function () {
                    console.log(i);
                }, 1000);
            })(i);
        }
        console.log(i);//5 ---（1秒后）0 1 2 3 4（几乎会同时输出）
        //立即执行函数只是函数的一种调用方式，只是声明完之后立即执行，这类函数一般都只是调用一次，调用完之后会立即销毁，不会占用内存。

        //闭包则主要是让外部函数可以访问内部函数的作用域，也减少了全局变量的使用，
        //保证了内部变量的安全，但因被引用的内部变量不能被销毁，增大了内存消耗，使用不当易造成内存泄露
    </script>
</body>

</html>